package com.ruoyi.system.service.report.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.Evaluating.EvaluationResult;
import com.ruoyi.system.domain.Evaluating.IndicatorEvaluationScore;
import com.ruoyi.system.domain.dto.IndicatorScoreDto;
import com.ruoyi.system.domain.dto.ReportInfoDto;
import com.ruoyi.system.domain.po.Report;
import com.ruoyi.system.domain.standard_relevant.Standard;
import com.ruoyi.system.mapper.Evaluating.EvaluationResultMapper;
//import com.ruoyi.system.mapper.Evaluating.IndicatorEvaluationScoreMapper;
import com.ruoyi.system.mapper.report.ReportMapper;
import com.ruoyi.system.mapper.standard.StandardMapper;
import com.ruoyi.system.service.report.IReportService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.drawingml.x2006.chart.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTShapeProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 评估报告Service业务层处理
 */
@Slf4j
@Service
public class ReportServiceImpl implements IReportService {
    @Autowired
    private ReportMapper reportMapper;

    @Autowired
    private StandardMapper standardMapper;

    @Autowired
    private EvaluationResultMapper resultMapper;

    @Autowired
    private EvaluationResultMapper scoreMapper;

    @Override
    public Report selectReportById(Long id) {
        return reportMapper.selectReportById(id);
    }

    @Override
    public List<Report> selectReportList(String reportName, Date startTime, Date endTime) {
        return reportMapper.selectReportList(reportName, startTime, endTime);
    }

    @Override
    public int insertReport(Report report) {

        report.setEvaluationDate(report.getCreateTime());
        return reportMapper.insertReport(report);
    }
    @Override
    public int batchInsert(List<Report> reportList) {
        return reportMapper.batchInsert(reportList);
    }

    @Override
    public int deleteReportByIds(Long[] ids) {
        return reportMapper.deleteReportByIds(ids);
    }

    public ReportInfoDto selectReportInfoById(Long id) {
        Report report = reportMapper.selectReportById(id);
        String standardCode=report.getStandardCode();
        long resultId=report.getEvaluationResultId();

        //1.标准信息
        Standard standard=standardMapper.selectStandardByCode(standardCode);

        //2.评价结果信息：包含总评信息+指标体系
        EvaluationResult result=resultMapper.selectEvaluationResultById(resultId);

        //3.通过resultId获取指标得分+组合权重详情，返回结果是List<IndicatorEvaluationScore>
        List<IndicatorEvaluationScore> scoreList = scoreMapper.selectIndicatorEvaluationScoreResultById(resultId);

        ReportInfoDto reportInfo = new ReportInfoDto();
        reportInfo.setStandard(standard);
        reportInfo.setResult(result);
        reportInfo.setIndicatorScores(scoreList);

        return reportInfo;
    }

    /**
     * 导出报告
     * 前面的详细信息是查别人的[没存在数据库中]，这里导出报告
     * 有得查一遍，有没有好点的解决方案呢？
     * */
    @SneakyThrows
    @Override
    public void exportReportToWord(Long id, OutputStream outputStream) throws IOException {

        ReportInfoDto reportInfo = selectReportInfoById(id);


        try (InputStream fis = getClass().getClassLoader().getResourceAsStream("template.docx");
             XWPFDocument document = new XWPFDocument(fis)) {

            // 替换文档中的占位符
            for (XWPFParagraph paragraph : document.getParagraphs()) {
                for (XWPFRun run : paragraph.getRuns()) {
                    String text = run.getText(0);
                    if (text != null) {
                        text = text.replace("${classificationCode}", reportInfo.getStandard().getClassificationCode());
                        text = text.replace("${standardName}", reportInfo.getStandard().getStandardName());
                        text=  text.replace("${organization}",reportInfo.getStandard().getOrganization());
                        text = text.replace("${standardCode}", reportInfo.getStandard().getStandardCode());
//                        text = text.replace("${remark}", reportInfo.getStandard().getRemark());
                        text = text.replace("${systemName}", reportInfo.getResult().getProjectName());
                        text = text.replace("${evaluateDate}", reportInfo.getResult().getEvaluateDate().toString());
                        text = text.replace("${outputValue}", reportInfo.getResult().getOutputValue().toString());
                        run.setText(text, 0);
                    }
                }
            }



            // 添加指标权重表格
            addIndicatorWeightsTable(document, reportInfo);

            XWPFParagraph chartParagraph = document.createParagraph();
            XWPFRun chartRun = chartParagraph.createRun();
            chartRun.addBreak();

            // 创建饼图并插入文档
            createPieChart(document, reportInfo);
            XWPFParagraph summaryParagraph = document.createParagraph();
            XWPFRun summaryRun = summaryParagraph.createRun();
            summaryRun.setText("总评结果：" + reportInfo.getResult().getOutputValue());
            summaryRun.addBreak(); // 添加换行符

            // 添加指标得分表格
            addIndicatorScoresTable(document, reportInfo);

            document.write(outputStream);
        }
    }

    private void createPieChart(XWPFDocument document, ReportInfoDto reportInfo) throws IOException, InvalidFormatException {
        XWPFChart chart = document.createChart();

        // 设置图表的宽度和高度
        // Set the size of the chart
        chart.setChartBoundingBox( 15 * Units.EMU_PER_CENTIMETER, 10 * Units.EMU_PER_CENTIMETER); // 10x10 cm

        // 设置图表标题
        chart.setTitleText("各项指标权重饼图");
        chart.setTitleOverlay(false);

        // 创建图表数据
        XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
        XDDFDataSource<String> categories = XDDFDataSourcesFactory.fromArray(
                reportInfo.getIndicatorScores().stream().map(IndicatorEvaluationScore::getIndicatorName).toArray(String[]::new));
        XDDFNumericalDataSource<Float> values = XDDFDataSourcesFactory.fromArray(
                reportInfo.getIndicatorScores().stream().map(IndicatorEvaluationScore::getCombinationWeight).toArray(Float[]::new));
        XDDFChartData.Series series = data.addSeries(categories, values);
        series.setTitle("各项指标得分", null);

        // 绘制图表
        chart.plot(data);

        // 配置饼图
        XDDFPieChartData pieData = (XDDFPieChartData) data;
        pieData.setVaryColors(true);
        XDDFPieChartData.Series pieSeries = (XDDFPieChartData.Series) series;
        pieSeries.setExplosion(10L); // 设置爆炸效果
        chart.getCTChart().getPlotArea().getPieChartArray(0).addNewVaryColors().setVal(true);

        // 设置图例位置
        CTLegend legend = chart.getCTChart().addNewLegend();
        legend.addNewLegendPos().setVal(STLegendPos.B);
        legend.addNewOverlay().setVal(false);

    }

    private void addIndicatorScoresTable(XWPFDocument document, ReportInfoDto reportInfo) {
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.addBreak();
        run.setBold(true); // 设置加粗
        run.setFontSize(12); // 设置字体大小
        run.setText("指标得分");

        XWPFTable table = document.createTable();
        table.setWidth("100%");

        XWPFTableRow headerRow = table.getRow(0);
        setCellText(headerRow.getCell(0), "指标名称", true, 11);
        setCellText(headerRow.addNewTableCell(), "指标得分", true, 11);

        for (IndicatorEvaluationScore score : reportInfo.getIndicatorScores()) {
            XWPFTableRow row = table.createRow();
            setCellText(row.getCell(0), String.valueOf(score.getIndicatorName()), false, 9);
            setCellText(row.getCell(1), String.valueOf(score.getIndicatorValue()), false, 9);
        }
        setTableStyle(table);
    }

    private void addIndicatorWeightsTable(XWPFDocument document, ReportInfoDto reportInfo) {
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.addBreak();
        run.setBold(true); // 设置加粗
        run.setFontSize(12); // 设置字体大小
        run.setText("指标权重");

        XWPFTable table = document.createTable();

        XWPFTableRow headerRow = table.getRow(0);
        setCellText(headerRow.getCell(0), "指标名称", true, 11);
        setCellText(headerRow.addNewTableCell(), "指标权重", true, 11);

        for (IndicatorEvaluationScore score : reportInfo.getIndicatorScores()) {
            XWPFTableRow row = table.createRow();
            setCellText(row.getCell(0), String.valueOf(score.getIndicatorName()), false, 9);
            setCellText(row.getCell(1), String.valueOf(score.getCombinationWeight()), false, 9);
        }
        setTableStyle(table);
    }

    private void setCellText(XWPFTableCell cell, String text, boolean bold, int fontSize) {
        XWPFParagraph paragraph = cell.getParagraphs().get(0);
        XWPFRun run = paragraph.createRun();
        run.setText(text);
        run.setBold(bold);
        run.setFontSize(fontSize);
        paragraph.setAlignment(ParagraphAlignment.CENTER);
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
    }

    private void setTableStyle(XWPFTable table) {
        table.setWidth("100%");
        table.setCellMargins(100, 100, 100, 100); // 设置单元格内边距

        // 设置表格边框样式
        table.getCTTbl().getTblPr().getTblBorders().getInsideH().setSz(BigInteger.valueOf(10));
        table.getCTTbl().getTblPr().getTblBorders().getInsideV().setSz(BigInteger.valueOf(10));
        table.getCTTbl().getTblPr().getTblBorders().getTop().setSz(BigInteger.valueOf(10));
        table.getCTTbl().getTblPr().getTblBorders().getBottom().setSz(BigInteger.valueOf(10));
        table.getCTTbl().getTblPr().getTblBorders().getLeft().setSz(BigInteger.valueOf(10));
        table.getCTTbl().getTblPr().getTblBorders().getRight().setSz(BigInteger.valueOf(10));
    }
}
